/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023.
 * Description: rtos its enhance feature functions
 * Author: huyizhou
 * Create: 2023-09-14
 */

#include <linux/of.h>
#include <linux/ioport.h>
#include <asm/memory.h>
#include <linux/of_address.h>
#include "irq-gic-common.h"

/*
 * Describes reserved memory region in interrupt controller.
 * The memory reserved: [pa_start, pa_end)
 */
struct of_resv its_gicr_rsv;
struct of_resv *gicr_resv;

struct of_resv *get_resv_mem(void)
{
	return gicr_resv;
}

struct page *alloc_rsv_pages(unsigned long size)
{
	struct of_resv *resv = get_resv_mem();
	unsigned long pa;
	unsigned long pa_next;
	if (!resv)
		return NULL;
	pa = ALIGN(resv->pa_start, size);
	pa_next = pa + size;

	/* Check if there is enough memory reserved to do another allocation */
	if (pa_next > resv->pa_end)
		return NULL;

	resv->pa_start = pa_next;
	memset(phys_to_virt(pa), 0, size);

	return phys_to_page(pa);
}

/*
 * Memory controller might have a reserved memory region to be used for ta
 * allocations. This is a requirement for kexec reboots.
 */
void __init its_of_mem_region(struct device_node *node,
				     struct of_resv **resv,
				     struct of_resv *resv_buf)
{
	struct device_node *np = of_parse_phandle(node, "memory-region", 0);
	struct resource mem_res;

	if (!np)
		return;

	if (of_address_to_resource(np, 0, &mem_res)) {
		pr_warn("%pOF: address to resource failed\n", np);
		return;
	}

	resv_buf->pa_start = mem_res.start;
	resv_buf->pa_end = mem_res.start + resource_size(&mem_res);
	*resv = resv_buf;
}
